package client;

import com.jme3.light.DirectionalLight;
import com.jme3.light.PointLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.filters.BloomFilter;
import com.jme3.post.filters.DepthOfFieldFilter;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.shadow.PssmShadowRenderer;
import com.jme3.shadow.PssmShadowRenderer.CompareMode;
import com.jme3.shadow.PssmShadowRenderer.FilterMode;

/**
 *
 * @author Ben
 * Purpose: Sets up and controls the lighting and processing effects in the engine
 */
public class LightingController 
{
    DirectionalLight playerlight = new DirectionalLight();
    DirectionalLight guilight = new DirectionalLight();
    private PssmShadowRenderer shadows;  
    private DepthOfFieldFilter dof;
    SSAOFilter ssao;
    BloomFilter bloom;
    private float curNear;
    
    /*
    setup_light:
    creates an omnidirectional light to light up the scene
    //TODO: find right lighting color/direction for general scenes
    */
    public void setupLight()
    {
        playerlight.setDirection(new Vector3f(-.25f, -.25f, -.10f));
        playerlight.setColor(ColorRGBA.Yellow.mult(0.45f).add(ColorRGBA.White.mult(0.55f)).add(ColorRGBA.Red.mult(0.25f)).add(ColorRGBA.Black.mult(0.2f)));
        guilight.setColor(playerlight.getColor());
        guilight.setDirection(playerlight.getDirection().normalize());
        Main.appref.getRootNode().addLight(playerlight);
        Main.appref.getGuiNode().addLight(guilight);
    }
    
    /*
    recalculate_shadows:
    reloads the shadow processor to prevent any inconsistencies or artifacts
    */
    public void redoShadows()
    {
        Main.appref.getViewPort().removeProcessor(shadows);
        Main.appref.getViewPort().removeProcessor(Main.fpp);
        shadows.cleanup();
        Main.appref.getViewPort().addProcessor(shadows);
        Main.appref.getViewPort().addProcessor(Main.fpp);
    }
    
    /*
    remove_bloom:
    function to remove the bloom processor
    */
    public void removeBloom()
    {
        Main.appref.getViewPort().removeProcessor(Main.fpp);
        Main.fpp.removeFilter(bloom);
        Main.appref.getViewPort().addProcessor(Main.fpp);
    }
    
    /*
    add_bloom:
    function to add the bloom processor
    */
    public void addBloom()
    {
        Main.appref.getViewPort().removeProcessor(Main.fpp);
        Main.fpp.addFilter(bloom);
        Main.appref.getViewPort().addProcessor(Main.fpp);
    }
    
    /*
    remove_ssao:
    function to remove the ssao processor
    */
    public void removeSSAO()
    {
        Main.appref.getViewPort().removeProcessor(Main.fpp);
        Main.fpp.removeFilter(ssao);
        Main.appref.getViewPort().addProcessor(Main.fpp);
    }
    
    /*
    add_ssao:
    function to add the ssao processor
    */
    public void addSSAO()
    {
        Main.appref.getViewPort().removeProcessor(Main.fpp);
        Main.fpp.addFilter(ssao);
        Main.appref.getViewPort().addProcessor(Main.fpp);
    }
    
    public void updateViews(float near)
    {
        curNear = near;
        dof.setFocusRange(curNear);
        if(curNear <= 25)
        {
            shadows.setLambda(1f);
        }
        if(curNear >= 26 && curNear <= 50)
        {
            shadows.setLambda(0.85f);
        }
        if(curNear >= 51 && curNear <= 75)
        {
            shadows.setLambda(0.75f);
        }
        if(curNear >= 76 && curNear <= 100)
        {
            shadows.setLambda(0.65f);
        }
        if(curNear >= 101 && curNear <= 150)
        {
            shadows.setLambda(0.35f);
        }
        if(curNear >= 151 && curNear <= 200)
        {
            shadows.setLambda(0.25f);
        }
    }
    /*
    setup_shadows:
    sets up the shadow renderers and post processing filters.
    */
    public void setupShadows()
    {
        shadows = new PssmShadowRenderer(Main.appref.getAssetManager(), 1024, 3);
        bloom=new BloomFilter();
        shadows.setDirection(new Vector3f(-.10f, -.10f, -.10f).normalizeLocal()); // light direction
        ssao = new SSAOFilter(8f, 1.2f, 0.55f, 0.1f);
        Main.fpp.addFilter(ssao);
        Main.fpp.addFilter(bloom);
        dof = new DepthOfFieldFilter();
        dof.setFocusDistance(0);
        dof.setFocusRange(50);
        dof.setBlurScale(0.75f);
        Main.fpp.addFilter(dof);
        bloom.setBloomIntensity(0.2f);
        shadows.setFilterMode(FilterMode.Bilinear);
        shadows.setCompareMode(CompareMode.Hardware);
        shadows.setLambda(1f);
        shadows.setShadowIntensity(0.8f);
        Main.appref.getViewPort().addProcessor(shadows);
    }
}
